Orders Provider
Provider that supplies data about orders for the selected trading instrument and manages order operations (create, update, remove). The chart listens to ordersPublisher
, a flow of order data updates, and reacts to changes in it by updating the displayed information accordingly.
Whenever there is new order data emitted by ordersPublisher
, the chart updates to reflect this new data, ensuring that the visual representation of the trading orders is always up-to-date and accurate.
import Combine/// A protocol for managing order data and operations for a specific trading instrument.////// The `OrdersProvider` protocol defines the required functionalities for any provider that supplies/// order data and manages order operations (create, update, remove) for a presented symbol./// Conforming types must implement the necessary publishers to push relevant order updates and/// provide methods for order management operations.////// This protocol is useful for applications that need to display and manage trading orders/// based on the selected financial instrument.public protocol OrdersProvider {/// A publisher that emits a dictionary of orders mapped by their IDs.////// The publisher sends updates as a result of order data changes, providing the current/// state of all orders for the selected symbol. The dictionary uses `Order.ID` as keys/// and `Order` objects as values.////// Observes the order lines updates. We expect to be the full list of orders - no partial updates,/// for now the full list will be replaced.var ordersPublisher: AnyPublisher<[Order.ID : Order], Never> { get }/// The protection offset value used for order placement calculations.////// This value represents the minimum distance (in price units) that protection orders should be/// placed from the original order price.var protectionOffset: Double { get }/// Changes the instrument symbol for which orders are being managed.////// This method updates the provider to handle orders for a different trading instrument./// When called, the provider should clear existing order data and begin managing orders/// for the new symbol.////// - Parameter symbol: The instrument symbol (e.g., "AAPL", "TSLA") for which the orders should be managed.func changeSymbol(_ symbol: Symbol)/// Creates a new order for the current symbol.////// This method initiates the creation of a new trading order. The provider should/// process the order creation request and update the `ordersPublisher` with the new order/// once it has been successfully created.////// - Parameter order: The `Order` object containing the details of the order to be created.func createOrder(_ order: Order)/// Updates an existing order with new parameters.////// This method modifies an existing order with updated information. The provider should/// process the order update request and update the `ordersPublisher` with the modified order/// once the update has been successfully applied.////// - Parameter order: The `Order` object containing the updated order details.func updateOrder(_ order: Order)/// Removes an existing order from the system.////// This method cancels or deletes an existing order. The provider should process the/// order removal request and update the `ordersPublisher` to reflect the removal of the order/// once it has been successfully cancelled or deleted.////// - Parameter order: The `Order` object to be removed from the system.func removeOrder(_ order: Order)}
Order data
/// Represents a trading order with all necessary details for order management.////// The `Order` structure holds data related to a specific trading order, including its type,/// side (buy/sell), quantity, price information, and optional protection parameters./// It includes order identification, execution parameters, and risk management settings.////// - Commonly used in trading applications to represent pending orders and their states.public struct Order: Codable, Hashable {/// Unique identifier for the order.public var id: ID/// The type of the order (e.g., market, limit, stop).public var orderType: OrderType/// The side of the order (buy or sell).public var side: OrderSide/// The quantity of the instrument to be traded.public var quantity: Double/// The limit price for limit orders (optional).public var limitPrice: Double?/// The stop price for stop orders (optional).public var stopPrice: Double?/// Flag indicating whether OCO (One-Cancels-Other) orders can be created.public var canCreateOCO: Bool?/// Optional data attributes for custom rendering and external project integration.public var data: [String: String]?/// Type alias for order ID.public typealias ID = String/// Enum representing the side of an order.public enum OrderSide: String, Codable, CaseIterable {case buy = "buy"case sell = "sell"}/// Enum representing the type of an order.public enum OrderType: String, Codable, CaseIterable {case market = "market"case limit = "limit"case stop = "stop"}}
Default implementation
If you haven't implemented an orders data provider earlier and need a basic implementation to get started, you can use our default provider. This implementation creates a simple in-memory storage for orders and can be extended to integrate with your specific trading system.
Default implementation code:
import Foundationimport Combineimport DXChartfinal class DXOrdersProvider: DXChart.OrdersProvider {typealias ID = DXChart.Order.IDtypealias Order = DXChart.Ordertypealias OrdersCache = [Symbol : [ID : Order]]private var ordersSubject: CurrentValueSubject<[ID :Order], Never>var ordersPublisher: AnyPublisher<[ID :Order], Never> {ordersSubject.eraseToAnyPublisher()}var protectionOffset: Double = 50var cache: OrdersCache = [:]private var storage = PersistentStorage()private var symbol: Symbolprivate var key = "orders"init(symbol: String, storage: PersistentStorage = PersistentStorage()) {self.symbol = symbolself.storage = storagedo {self.cache = try storage.retrieve(OrdersCache.self, forKey: key)} catch {debugPrint("error loading orders: (error)")cache[symbol] = [:]}ordersSubject = CurrentValueSubject(cache[symbol] ?? [:])}func changeSymbol(_ symbol: Symbol) {self.symbol = symbolif let orders = cache[symbol] {ordersSubject.send(orders)} else {cache[symbol] = [:]ordersSubject.send([:])}}func createOrder(_ order: DXChart.Order) {if cache[order.symbol] == nil {cache[order.symbol] = [:]}cache[order.symbol]?[order.id] = ordertry? storage.store(cache, forKey: key)ordersSubject.send(cache[symbol]!)}func updateOrder(_ order: DXChart.Order) {guard cache[order.symbol]?[order.id] != nil else {debugPrint(#function, "Order can't be updated. Order not found: (order)")return}cache[order.symbol]?[order.id] = ordertry? storage.store(cache, forKey: key)ordersSubject.send(cache[order.symbol]!)}func removeOrder(_ order: Order) {guard cache[order.symbol]?[order.id] != nil else {debugPrint(#function, "Order can't be deleted. Order not found: (order)")return}cache[order.symbol]?[order.id] = niltry? storage.store(cache, forKey: key)ordersSubject.send(cache[order.symbol]!)}}
Integration
To integrate the Orders Provider with your trading system, you should:
- Implement the instance that will align the OrdersProvider protocol with your specific trading logic
- Specify this instance in the chart using the
DataProvider
property - Specify your data provider when initializing the ChartScreen module.
The provider should maintain consistency between the chart's visual representation and your trading system's order state.
Tips
Trading orders are supported only in the ChartScreen module, not in ChartView.